/*
 * Copyright (c) 2007 jMouse Gestures
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * * Neither the name of 'jMouse Gestures' nor the names of its contributors
 *   may be used to endorse or promote products derived from this software
 *   without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.jmg.space;

import java.io.Serializable;


/**
 * JMGLocation class.
 *
 * @author  Christopher Martin
 * @version $Id: JMGLocation.java 12 2007-05-24 11:54:07Z GentlemanHal $
 */
public class JMGLocation implements 
    Location,
    Cloneable,
    Serializable
{
    /** Serial Version UID */
    private static final long serialVersionUID = 1L;
    
    protected float x, y, z;
    
    
    
    
    
    /** 
     * Creates a new instance of <code>JMGLocation</code> with the default
     * location of (0, 0, 0).
     */
    public JMGLocation() {
        this(0f, 0f, 0f);
    }
    
    /**
     * Creates a new instance of <code>JMGLocation</code>.
     *
     * @param x The x position.
     * @param y The y position.
     * @param z The z position.
     */
    public JMGLocation(float x, float y, float z) {
        this.x = x;
        this.y = y;
        this.z = z;
    }

    
    
    
    
    /**
     * Returns the x location.
     * 
     * @return The x location.
     */
    public float getX() {
        return x;
    }

    /**
     * Returns the y location.
     * 
     * @return The y location.
     */
    public float getY() {
        return y;
    }

    /**
     * Returns the z location.
     * 
     * @return The z location.
     */
    public float getZ() {
        return z;
    }
    
    /**
     * Returns the distance between this and the given 
     * <code>Location</code>.
     * 
     * @param  loc The location to find the distance to.
     * @return The distance.
     * @throws java.lang.IllegalArgumentException If a <code>null</code>
     *         argument is passed.
     */
    public float distance(Location loc) 
        throws IllegalArgumentException
    {
        if (null == loc) {
            throw new IllegalArgumentException("loc was null!");
        }
        
        
        float dx = x - loc.getX();
        float dy = y - loc.getY();
        float dz = z - loc.getZ();
        
        return (float) Math.sqrt(dx * dx + dy * dy + dz * dz);
    }
    
    
    
    
    
    /**
     * Returns a string representation of the object.
     *
     * @return a string representation of the object.
     */
    @Override
    public String toString() {
        StringBuilder buf = new StringBuilder(40);
        
        buf.append(getClass().getName()); 
        buf.append("[x=").append(x); 
        buf.append(",y=").append(y); 
        buf.append(",z=").append(z);
        buf.append(']');
        
        return buf.toString();
    }

    /**
     * Creates and returns a copy of this object.
     * 
     * @return a clone of this instance.
     * @exception CloneNotSupportedException  if the object's class does not
     *               support the <code>Cloneable</code> interface. Subclasses
     *               that override the <code>clone</code> method can also
     *               throw this exception to indicate that an instance cannot
     *               be cloned.
     * @see java.lang.Cloneable
     */
    @Override
    public Object clone() 
        throws CloneNotSupportedException 
    {
        JMGLocation retValue = (JMGLocation) super.clone();
        
        retValue.x = x;
        retValue.y = y;
        retValue.z = z;
        
        return retValue;
    }

    /**
     * Returns a hash code value for the object.
     * 
     * @return a hash code value for this object.
     * @see java.lang.Object#equals(java.lang.Object)
     * @see java.util.Hashtable
     */
    @Override
    public int hashCode() {
        return Float.floatToIntBits(x) * 13 + 
               Float.floatToIntBits(y) * 13 + 
               Float.floatToIntBits(z) * 13;
    }

    /**
     * Indicates whether some other object is "equal to" this one.
     * 
     * @param obj   the reference object with which to compare.
     * @return <code>true</code> if this object is the same as the obj
     *          argument; <code>false</code> otherwise.
     * @see #hashCode()
     * @see java.util.Hashtable
     */
    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        
        if (null == obj || obj.getClass() != getClass()) {
            return false;
        }
        
        JMGLocation other = (JMGLocation) obj;
        
        return other.x == x && other.y == y && other.z == z;
    }
    
}
